home *** CD-ROM | disk | FTP | other *** search
Wrap
#! /bin/sh # # Script to start or stop laptop_mode, and to control various settings of the # kernel, hardware etc. that influence power consumption. # # This script is a part of Laptop Mode Tools. If you are running a supported # power management daemon, this script will be automatically called on power # state change. # # Configure laptop mode tools in /etc/laptop-mode/laptop-mode.conf, and in # the broken-out config files in /etc/laptop-mode/conf.d. # # Please consult the manual pages laptop-mode.conf(8) and laptop_mode(8) for # additional information. # # Maintainer: Bart Samwel (bart@samwel.tk) # Project home page: http://samwel.tk/laptop_mode # # Contributors to this script: Bart Samwel # Kiko Piris # Micha Feigin # Andrew Morton # Herve Eychenne # Dax Kelson # Jan Polacek # ... and many others that I've stopped # keeping track of. # # Based on a script for Linux 2.4 written by Jens Axboe. # ############################################################################# set -a # The laptop mode tools version number. Extracted by the installer makefile # as well, so don't change the format! LMTVERSION=1.47 # This script is loaded from multiple scripts to set the config defaults # and to read the configuration on top of those. Only when the command is # recognized does this script do anything else. VERBOSE_OUTPUT=0 ENABLE_LAPTOP_MODE_ON_BATTERY=1 ENABLE_LAPTOP_MODE_ON_AC=0 ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED=0 PARTITIONS="auto /dev/mapper/*" LM_BATT_MAX_LOST_WORK_SECONDS=600 LM_AC_MAX_LOST_WORK_SECONDS=360 DEF_MAX_AGE=30 LM_READAHEAD=3072 NOLM_READAHEAD=128 CONTROL_READAHEAD=1 CONTROL_NOATIME=0 USE_RELATIME=1 CONTROL_HD_IDLE_TIMEOUT=1 LM_AC_HD_IDLE_TIMEOUT=4 # 20 seconds LM_BATT_HD_IDLE_TIMEOUT=4 # 20 seconds NOLM_HD_IDLE_TIMEOUT=244 # 2 hours DEF_UPDATE=5 DEF_XFS_AGE_BUFFER=15 DEF_XFS_SYNC_INTERVAL=30 DEF_XFS_BUFD_INTERVAL=1 XFS_HZ=100 CONTROL_MOUNT_OPTIONS=1 BATT_HD_POWERMGMT=1 LM_AC_HD_POWERMGMT=254 NOLM_AC_HD_POWERMGMT=254 CONTROL_HD_POWERMGMT=0 CONTROL_HD_WRITECACHE=0 NOLM_AC_HD_WRITECACHE=1 NOLM_BATT_HD_WRITECACHE=0 LM_HD_WRITECACHE=0 LM_DIRTY_RATIO=60 LM_DIRTY_BACKGROUND_RATIO=1 NOLM_DIRTY_BACKGROUND_RATIO=10 NOLM_DIRTY_RATIO=40 LM_SECONDS_BEFORE_SYNC=2 BATT_CPU_MAXFREQ=medium BATT_CPU_MINFREQ=slowest BATT_CPU_GOVERNOR=ondemand BATT_CPU_IGNORE_NICE_LOAD=1 LM_AC_CPU_MAXFREQ=fastest LM_AC_CPU_MINFREQ=slowest LM_AC_CPU_GOVERNOR=ondemand LM_AC_CPU_IGNORE_NICE_LOAD=1 NOLM_AC_CPU_MAXFREQ=fastest NOLM_AC_CPU_MINFREQ=slowest NOLM_AC_CPU_GOVERNOR=ondemand NOLM_AC_CPU_IGNORE_NICE_LOAD=0 CONTROL_CPU_FREQUENCY=0 HD="/dev/[hs]d[abcdefgh]" CONTROL_SYSLOG_CONF=0 LM_AC_SYSLOG_CONF=/etc/syslog-on-ac-with-lm.conf NOLM_AC_SYSLOG_CONF=/etc/syslog-on-ac-without-lm.conf BATT_SYSLOG_CONF=/etc/syslog-on-battery.conf SYSLOG_CONF_SIGNAL_PROGRAM=syslogd SYSLOG_CONF=/etc/syslog.conf CONTROL_DPMS_STANDBY=0 BATT_DPMS_STANDBY=300 LM_AC_DPMS_STANDBY=1200 NOLM_AC_DPMS_STANDBY=1200 CONTROL_CPU_THROTTLING=0 BATT_CPU_THROTTLING=medium LM_AC_CPU_THROTTLING=minimum NOLM_AC_CPU_THROTTLING=minimum CONTROL_START_STOP=1 CONTROL_TERMINAL=0 TERMINALS="/dev/vc/1 /dev/vcs1" BATT_TERMINAL_BLANK_MINUTES=1 BATT_TERMINAL_POWERDOWN_MINUTES=2 LM_AC_TERMINAL_BLANK_MINUTES=10 LM_AC_TERMINAL_POWERDOWN_MINUTES=10 NOLM_AC_TERMINAL_BLANK_MINUTES=10 NOLM_AC_TERMINAL_POWERDOWN_MINUTES=50 ENABLE_AUTO_HIBERNATION=0 HIBERNATE_COMMAND=/usr/sbin/hibernate AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL=1 DISABLE_LAPTOP_MODE_ON_CRITICAL_BATTERY_LEVEL=1 AUTO_HIBERNATION_BATTERY_CHARGE_MAH=0 AUTO_HIBERNATION_BATTERY_CHARGE_MWH=0 MINIMUM_BATTERY_CHARGE_MAH=0 MINIMUM_BATTERY_CHARGE_MWH=0 ASSUME_SCSI_IS_SATA=1 CONTROL_BRIGHTNESS=0 BATT_BRIGHTNESS_COMMAND=false LM_AC_BRIGHTNESS_COMMAND=false NOLM_AC_BRIGHTNESS_COMMAND=false # No default on these ones -- we need to detect if they have been set, for # backward compatibility with MINIMUM_BATTERY_MINUTES etc. AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT= MINIMUM_BATTERY_CHARGE_PERCENT= # Backward compatibility variable that is sometimes # set externally (Debian init system) unset VERBOSE # Source config. Some config settings have been moved from the main config file # to modular configuration files, and to support existing laptop-mode.conf # files from earlier versions, we source the modular configuration files FIRST. if [ -d /etc/laptop-mode/conf.d ] ; then for CONF in /etc/laptop-mode/conf.d/*.conf ; do if [ -r "$CONF" ] ; then . "$CONF" else echo "Warning: Configuration file $CONF is not readable, skipping." fi done fi if [ -r /etc/laptop-mode/laptop-mode.conf ] ; then . /etc/laptop-mode/laptop-mode.conf else echo "$0: Configuration file /etc/laptop-mode/laptop-mode.conf not present or not readable." exit 1 fi # Support for old config settings if [ "$AC_HD" != "" ] ; then AC_HD_WITHOUT_LM="$AC_HD" AC_HD_WITH_LM="$AC_HD" fi if [ "$VERBOSE" != "" ] ; then VERBOSE_OUTPUT="$VERBOSE" fi if [ "$CPU_MAXFREQ" != "" ] ; then BATT_CPU_MAXFREQ="$CPU_MAXFREQ" fi if [ "$MAX_AGE" != "" ] ; then LM_BATT_MAX_LOST_WORK_SECONDS="$MAX_AGE" LM_AC_MAX_LOST_WORK_SECONDS="$MAX_AGE" fi if [ "$DEF_AGE" != "" ] ; then DEF_MAX_AGE="$DEF_AGE" fi if [ "$LAPTOP_MODE_ALWAYS_ON" != "" ] ; then ENABLE_LAPTOP_MODE_ALWAYS="$LAPTOP_MODE_ALWAYS_ON" fi if [ "$LM_WHEN_LID_CLOSED" != "" ] ; then ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED="$LM_WHEN_LID_CLOSED" fi if [ "$REMOUNT_PARTITIONS" != "" ] ; then PARTITIONS="$REMOUNT_PARTITIONS" fi if [ "$READAHEAD" != "" ] ; then LM_READAHEAD="$READAHEAD" fi if [ "$DO_REMOUNT_NOATIME" != "" ] ; then CONTROL_NOATIME="$DO_REMOUNT_NOATIME" fi if [ "$DO_HD" != "" ] ; then CONTROL_HD_IDLE_TIMEOUT="$DO_HD" fi if [ "$AC_HD_WITH_LM" != "" ] ; then LM_AC_HD_IDLE_TIMEOUT="$AC_HD_WITH_LM" fi if [ "$AC_HD_WITHOUT_LM" != "" ] ; then NOLM_HD_IDLE_TIMEOUT="$AC_HD_WITHOUT_LM" fi if [ "$BATT_HD" != "" ] ; then LM_BATT_HD_IDLE_TIMEOUT="$BATT_HD" fi if [ "$DO_REMOUNTS" != "" ] ; then CONTROL_MOUNT_OPTIONS="$DO_REMOUNTS" fi if [ "$DO_HD_POWERMGMT" != "" ] ; then CONTROL_HD_POWERMGMT="$DO_HD_POWERMGMT" fi if [ "$AC_HDPARM_POWERMGMT_WITH_LM" != "" ] ; then LM_AC_HD_POWERMGMT="$AC_HDPARM_POWERMGMT_WITH_LM" fi if [ "$AC_HDPARM_POWERMGMT_WITHOUT_LM" != "" ] ; then NOLM_AC_HD_POWERMGMT="$AC_HDPARM_POWERMGMT_WITHOUT_LM" fi if [ "$BATT_HDPARM_POWERMGMT" != "" ] ; then BATT_HD_POWERMGMT="$BATT_HDPARM_POWERMGMT" fi if [ "$DO_WRITECACHE" != "" ] ; then CONTROL_HD_WRITECACHE="$DO_WRITECACHE" fi if [ "$AC_WRITECACHE_WITHOUT_LM" != "" ] ; then NOLM_AC_HD_WRITECACHE="$AC_WRITECACHE_WITHOUT_LM" fi if [ "$BATT_WRITECACHE" != "" ] ; then LM_HD_WRITECACHE="$BATT_WRITECACHE" fi if [ "$DIRTY_RATIO" != "" ]; then LM_DIRTY_RATIO="$DIRTY_RATIO" fi if [ "$DIRTY_BACKGROUND_RATIO" != "" ] ; then LM_DIRTY_BACKGROUND_RATIO="$DIRTY_BACKGROUND_RATIO" fi if [ "$DEF_DIRTY_RATIO" != "" ]; then NOLM_DIRTY_RATIO="$DEF_DIRTY_RATIO" fi if [ "$DEF_DIRTY_BACKGROUND_RATIO" != "" ] ; then NOLM_DIRTY_BACKGROUND_RATIO="$DEF_DIRTY_BACKGROUND_RATIO" fi if [ "$DO_CPU" != "" ] ; then CONTROL_CPU_FREQUENCY="$DO_CPU" fi if [ "$CONTROL_CPU_MAXFREQ" != "" ] ; then CONTROL_CPU_FREQUENCY="$CONTROL_CPU_MAXFREQ" fi if [ "$AC_CPU_MAXFREQ_WITH_LM" != "" ] ; then LM_AC_CPU_MAXFREQ="$AC_CPU_MAXFREQ_WITH_LM" fi if [ "$AC_CPU_MAXFREQ_WITHOUT_LM" != "" ] ; then NOLM_AC_CPU_MAXFREQ="$AC_CPU_MAXFREQ_WITHOUT_LM" fi if [ "$DO_SYSLOG" != "" ] ; then CONTROL_SYSLOG_CONF="$DO_SYSLOG" fi if [ "$SYSLOG_SIGNAL_PROGRAM" != "" ] ;then SYSLOG_CONF_SIGNAL_PROGRAM="$SYSLOG_SIGNAL_PROGRAM" fi if [ "$AC_SYSLOG_WITH_LM" != "" ] ; then LM_AC_SYSLOG_CONF="$AC_SYSLOG_WITH_LM" fi if [ "$AC_SYSLOG_WITHOUT_LM" != "" ] ; then NOLM_AC_SYSLOG_CONF="$AC_SYSLOG_WITHOUT_LM" fi if [ "$BATT_SYSLOG" != "" ] ; then BATT_SYSLOG_CONF="$BATT_SYSLOG" fi if [ "$ENABLE_LAPTOP_MODE_ALWAYS" != "" ] ; then ENABLE_LAPTOP_MODE_ON_AC="$ENABLE_LAPTOP_MODE_ALWAYS" fi if [ "$MINIMUM_BATTERY_MINUTES" != "" -a "$MINIMUM_BATTERY_CHARGE_PERCENT" = "" ] ; then # Use a very conservative estimate (1% = 1 battery minute, 100 minutes in a battery) # for backward compatibility. MINIMUM_BATTERY_CHARGE_PERCENT="$MINIMUM_BATTERY_MINUTES" fi if [ -z "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then # Apply the default, now that we've determined that this is the minimum. MINIMUM_BATTERY_CHARGE_PERCENT=3 fi if [ "$AUTO_HIBERNATION_BATTERY_MINUTES" != "" -a "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" = "" ] ; then # Use a very conservative estimate (1% = 1 battery minute, 100 minutes in a battery) # for backward compatibility. AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT="$AUTO_HIBERNATION_BATTERY_MINUTES" fi if [ -z "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then # Apply the default, now that we've determined that this is the minimum. AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT=2 fi # Postprocessing if [ "$VERBOSE_OUTPUT" -ne 0 ] ; then OUTPUT="/dev/stdout" LM_VERBOSE="[ 1 = 1 ]" else OUTPUT="/dev/null" LM_VERBOSE="[ 1 = 0 ]" fi if [ "$PARTITIONS" = "" ] ; then PARTITIONS="auto /dev/mapper/*" fi # Expand shell wild cards immediately. PARTITIONS=$( echo $PARTITIONS ) TERMINALS=$( echo $TERMINALS ) # Convert seconds to hdparm -S format # Everything over 20 minutes is interpreted as 2 hours. seconds_to_hdparm_S() { if [ "$1" -eq 0 ] ; then # disable. echo 0 elif [ "$1" -gt 0 -a "$1" -lt 5 ] ; then # 5 seconds minimum echo 1 elif [ "$1" -le $((240*5)) ] ; then # Values between 1 and 240 signify increments of 5 seconds echo $(($1 / 5)) elif [ "$1" -lt $((30*60)) ] ; then # Values between 20 and 30 minutes are rounded up to 30 minutes. echo 241 elif [ "$1" -lt $((12*30*60)) ] ; then # Values between 30 minutes and 6 hours (exclusive) yield values between # 241 and 251, in 30-minute increments. echo $(( 240 + ($1 / (30*60)) )) else # Larger values effectively indicate no timeout at all. echo 0 fi } # Convert configured idle timeouts to hdparm -S format. if [ "$LM_AC_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then LM_AC_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $LM_AC_HD_IDLE_TIMEOUT_SECONDS) fi if [ "$LM_BATT_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then LM_BATT_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $LM_BATT_HD_IDLE_TIMEOUT_SECONDS) fi if [ "$NOLM_HD_IDLE_TIMEOUT_SECONDS" != "" ] ; then NOLM_HD_IDLE_TIMEOUT=$(seconds_to_hdparm_S $NOLM_HD_IDLE_TIMEOUT_SECONDS) fi if [ "$1" = "status" ] ; then # Display a status report. echo "Mounts:" mount | sed "s/^/ /" echo echo "Drive power status:" for disk in $HD; do if [ -r $disk ]; then hdparm -C $disk 2>/dev/null | sed "s/^/ /" else echo " Cannot read $disk, permission denied - $0 needs to be run as root" fi done echo echo "(NOTE: drive settings affected by Laptop Mode cannot be retrieved.)" echo echo "Readahead states:" cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do # skip funny stuff case "$FST" in rootfs|unionfs|tmpfs|squashfs|sysfs|usbfs|proc|devpts) continue ;; esac if [ -b $DEV ] ; then if [ -r $DEV ] ; then echo " $DEV: $((`blockdev --getra $DEV` / 2)) kB" else echo " Cannot read $DEV, permission denied - $0 needs to be run as root" fi fi done echo if [ -e /var/run/laptop-mode-tools/enabled ] ; then echo "Laptop Mode Tools is allowed to run: /var/run/laptop-mode-tools/enabled exists." else echo "Laptop Mode Tools is NOT allowed to run: /var/run/laptop-mode-tools/enabled does not exist." fi echo STATFILES="/proc/sys/vm/laptop_mode /proc/apm /proc/pmu/info /proc/sys/vm/bdflush /proc/sys/vm/dirty_ratio /proc/sys/fs/xfs/age_buffer /proc/sys/fs/xfs/sync_interval /proc/sys/fs/xfs/lm_age_buffer /proc/sys/fs/xfs/lm_sync_interval /proc/sys/vm/pagebuf/lm_flush_age /proc/sys/fs/xfs/xfsbufd_centisecs /proc/sys/fs/xfs/xfssyncd_centisecs /proc/sys/vm/dirty_background_ratio /proc/sys/vm/dirty_expire_centisecs /proc/sys/fs/xfs/age_buffer/centisecs /proc/sys/vm/dirty_writeback_centisecs /sys/devices/system/cpu/*/cpufreq/cpuinfo_*_freq /sys/devices/system/cpu/*/cpufreq/scaling_governor /proc/acpi/button/lid/*/state /proc/acpi/ac_adapter/*/state /proc/acpi/battery/*/state /sys/class/power_supply/*/online /sys/class/power_supply/*/state" for THISFILE in $STATFILES ; do if [ -e "$THISFILE" ] ; then echo "$THISFILE:" if [ -r "$THISFILE" ] ; then cat "$THISFILE" | sed "s/^/ /" else echo " Not accessible, permission denied - $0 needs to be run as root." fi echo fi done elif [ "$1" != "readconfig" -a "$1" != "defaults" ] ; then ############################################################################# KLEVEL="$(uname -r | { IFS='.-' read a b c echo $a.$b } )" KMINOR="$(uname -r | { IFS='.-' read a b c d # Strip any stuff from the end -- only the initial digits are part of the KMINOR. echo $c | sed -e 's/\([[:digit:]]*\).*/\1/' } )" case "$KLEVEL" in "2.4" ) ;; "2.6" ) ;; *) echo "Unhandled kernel version: $KLEVEL ('uname -r' = '$(uname -r)')" >&2 exit 1 ;; esac # Stop exporting everything -- what we do from here is private. set +a if [ "$1" = "--version" ] ; then echo "Laptop Mode Tools $LMTVERSION" exit 0 fi echo "Laptop Mode Tools $LMTVERSION" >> $OUTPUT if [ ! -e /proc/sys/vm/laptop_mode ] ; then echo "Kernel does not have support for laptop mode. Please apply the laptop mode" >&2 echo "patch or install a newer kernel." >&2 exit 1 fi if [ ! -w /proc/sys/vm/laptop_mode ] ; then echo "You do not have enough privileges to enable laptop_mode." >&2 exit 1 fi INIT=0 # Display info in init script format? FORCE=0 # Force reapplying the current state? #while [ "$1" != "" ] ; do # case "$1" in # init) INIT=1 ;; # force) FORCE=1 ;; # # Old options. We always do "auto" for any option now, but # # we still have to accept the options. # start) ;; # stop) ;; # auto) ;; # *) echo "Unrecognized option $1." # exit 1 ;; # esac # shift #done if [ "$1" = "init" ] || [ "$2" = "init" ]; then INIT=1 fi mkdir -p /var/run/laptop-mode-tools # Used to display laptop mode state later on. This is the enabled/disabled # state for laptop mode processing, it tells us nothing about whether laptop # mode is actually _active_. STATE=enabled if [ "$ENABLE_LAPTOP_MODE_ON_BATTERY" -eq 0 -a "$ENABLE_LAPTOP_MODE_ON_AC" -eq 0 -a "$ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED" -eq 0 ] ; then STATE=disabled fi # Determine the power state. # First try /sys/class/power_supply/* FOUND_SYS_CLASS_POWER_SUPPLY_AC=0 ON_AC=0 for POWER_SUPPLY in /sys/class/power_supply/* ; do if [ -f $POWER_SUPPLY/type ] ; then if [ "$(cat $POWER_SUPPLY/type)" = "Mains" ] ;then $LM_VERBOSE && echo "Determining power state from $POWER_SUPPLY/online." >> $OUTPUT FOUND_SYS_CLASS_POWER_SUPPLY_AC=1 if [ "$(cat $POWER_SUPPLY/online)" = 1 ] ; then ON_AC=1 fi fi fi done if [ $FOUND_SYS_CLASS_POWER_SUPPLY_AC = 1 ] ; then # Already found it! $LM_VERBOSE && echo "Not trying other options, already found a power supply." >> $OUTPUT elif [ -d /proc/acpi/ac_adapter ] ; then $LM_VERBOSE && echo "Determining power state from /proc/acpi/ac_adapter." >> $OUTPUT ADAPTERS_FOUND=0 ON_AC=0 for ADAPTER in /proc/acpi/ac_adapter/* ; do if [ -f $ADAPTER/state ] ; then ADAPTERS_FOUND=1 STATUS=`awk '/^state: / { print $2 }' $ADAPTER/state` if [ "$STATUS" = "on-line" ] ; then ON_AC=1 fi fi done if [ "$ADAPTERS_FOUND" -eq 0 ] ; then ON_AC=1 fi elif [ -f /proc/pmu/info ] ; then $LM_VERBOSE && echo "Determining power state from /proc/pmu/info." >> $OUTPUT if ( grep -q "^AC Power.*0$" /proc/pmu/info ) ; then $LM_VERBOSE && echo "/proc/pmu/info indicates absence of AC power." >> $OUTPUT ON_AC=0 else # It is possible that there is no AC Power = 1 in the file, # but we always assume AC power when we're not sure. ON_AC=1 $LM_VERBOSE && echo "/proc/pmu/info indicates presence of AC power." >> $OUTPUT fi elif [ -f /proc/apm ] ; then $LM_VERBOSE && echo "Determining power state from /proc/apm." >> $OUTPUT read D1 D2 D3 APM_AC_STATE D0 </proc/apm if [ "$APM_AC_STATE" = "0x00" ] ; then ON_AC=0 else ON_AC=1 fi else $LM_VERBOSE && echo "No /sys/class/power_supply, ACPI, APM or PMU power management information found -- assuming AC power is present." >> $OUTPUT ON_AC=1 fi # Determine whether to activate or deactivate laptop mode. ACTIVATE=0 if [ "$ON_AC" -eq 1 ] ; then if [ "$ENABLE_LAPTOP_MODE_ON_AC" -ne 0 ] ; then $LM_VERBOSE && echo "On AC power: Activating, because ENABLE_LAPTOP_MODE_ON_AC is set." >> $OUTPUT ACTIVATE=1 else $LM_VERBOSE && echo "On AC power: Deactivating, because ENABLE_LAPTOP_MODE_ON_AC is not set." >> $OUTPUT ACTIVATE=0 fi else if [ "$ENABLE_LAPTOP_MODE_ON_BATTERY" -ne 0 ] ; then $LM_VERBOSE && echo "On battery power: Activating, because ENABLE_LAPTOP_MODE_ON_BATTERY is set." >> $OUTPUT ACTIVATE=1 else $LM_VERBOSE && echo "On battery power: Deactivating, because ENABLE_LAPTOP_MODE_ON_BATTERY is not set." >> $OUTPUT ACTIVATE=0 fi fi if [ "$ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED" -ne 0 -a "$ACTIVATE" -eq 0 ] ; then if [ -x "`which hal-find-by-property`" ] ; then HAL_LID_BUTTON=$(hal-find-by-property --key "button.type" --string "lid") fi if [ "$HAL_LID_BUTTON" != "" ] ; then HAL_LID_BUTTON_STATE=$(hal-get-property --udi $(hal-find-by-property --key "button.type" --string "lid") --key "button.state.value") if [ "$HAL_LID_BUTTON_STATE" = "true" ] ; then $LM_VERBOSE && echo "Setting action to \"start\" because the lid is closed (says HAL)." >> $OUTPUT ACTIVATE=1 fi elif [ -f /proc/acpi/button/lid/*/state ] ; then if ( grep -q "closed" /proc/acpi/button/lid/*/state ) ; then $LM_VERBOSE && echo 'Setting action to "start" because the lid is closed (says /proc/acpi/button/lid/*/state).' >> $OUTPUT ACTIVATE=1 fi else echo "Warning: ENABLE_LAPTOP_MODE_WHEN_LID_CLOSED is set, but there is no file" echo "/proc/acpi/button/lid/.../state, and hal information is not available either!" fi fi # If the init script has not been run or has been run with the "stop" # argument, then we should never start laptop mode. if [ ! -f /var/run/laptop-mode-tools/enabled ] ; then $LM_VERBOSE && echo "Laptop mode disabled because /var/run/laptop-mode-tools/enabled is missing." >> $OUTPUT STATE=disabled fi if [ "$ACTIVATE" -eq 1 -a -f /etc/default/laptop-mode ] ; then . /etc/default/laptop-mode if ! ( echo "$ENABLE_LAPTOP_MODE" |grep y ) ; then $LM_VERBOSE && echo "Not starting laptop mode because it is disabled in /etc/default/laptop-mode." >> $OUTPUT STATE=disabled fi fi if [ "$1" = "start" ]; then STATE=enabled ACTIVATE=1; elif [ "$1" = "stop" ] || [ "$2" = "stop" ]; then STATE=disabled ACTIVATE=0; fi # Check whether we are allowed to activate the data-loss-sensitive stuff. # If the battery charge is too low, we want to disable this, but not the # other power-saving stuff. if [ "$ACTIVATE" -eq 0 ] ; then ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0 elif [ "$ON_AC" = 1 ] ; then $LM_VERBOSE && echo "On AC, not checking minimum battery charge." >> $OUTPUT ACTIVATE_WITH_POSSIBLE_DATA_LOSS=1 else ACTIVATE_WITH_POSSIBLE_DATA_LOSS=1 ENOUGH_CHARGE=0 ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=0 # Weird way of checking that /sys/class/power_supply is not empty -- but it works. if [ "$(echo /sys/class/power_supply/*)" != '/sys/class/power_supply/*' ] ; then $LM_VERBOSE && echo 'Not on AC and we have battery information in /sys/class/power_supply/BAT* -- checking minimum battery charge.' >> $OUTPUT for BATT in /sys/class/power_supply/* ; do BATT_TYPE=$(cat $BATT/type) $LM_VERBOSE && echo "$BATT is of type $BATT_TYPE." >> $OUTPUT if [ "$BATT_TYPE" != "Battery" ] ; then $LM_VERBOSE && echo "Not of type \"Battery\", skipping." >> $OUTPUT else PREV_ENOUGH_CHARGE=$ENOUGH_CHARGE PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION $LM_VERBOSE && echo "Checking levels for $BATT." >> $OUTPUT PRESENT=$(cat $BATT/present) $LM_VERBOSE && echo "Present: $PRESENT." >> $OUTPUT # Only do if the battery is present if [ "$PRESENT" -eq 1 ] ; then FOUND_AN_ENABLED_CHECK=0 FOUND_AN_ENABLED_HIBERNATION_CHECK=0 # Get the remaining capacity. IN_UAH=0 IN_UWH=0 if [ -f $BATT/charge_now ] ; then REMAINING=$(cat $BATT/charge_now) IN_UAH=1 # charge_* is in microAmpere-hours elif [ -f $BATT/energy_now ] ; then REMAINING=$(cat $BATT/energy_now) IN_UWH=1 # energy_* is in microWatt-hours else REMAINING=0 fi if [ -z "$REMAINING" -o "$REMAINING" -eq 0 ] ; then $LM_VERBOSE && echo "Battery does not report remaining charge. Perhaps it is not present?" >> $OUTPUT REMAINING=0 fi $LM_VERBOSE && echo "Remaining charge: $REMAINING" >> $OUTPUT if [ -f $BATT/charge_full_design ] ; then CAPACITY=$(cat $BATT/charge_full_design) elif [ -f $BATT/energy_full_design ] ; then CAPACITY=$(cat $BATT/energy_full_design) else CAPACITY=0 fi if [ -z "$CAPACITY" -o "$CAPACITY" -eq 0 ] ; then $LM_VERBOSE && echo "Battery does not report design full charge, using non-design full charge." >> $OUTPUT if [ -f $BATT/charge_full ] ; then CAPACITY=$(cat $BATT/charge_full) elif [ -f $BATT/energy_full_design ] ; then CAPACITY=$(cat $BATT/energy_full) else CAPACITY=0 fi if [ -z "$CAPACITY" -o "$CAPACITY" -eq 0] ; then $LM_VERBOSE && echo "Battery does not report non-design full charge." >> $OUTPUT CAPACITY=0 fi fi $LM_VERBOSE && echo "Full capacity: $CAPACITY" >> $OUTPUT # Check the charge percentage if [ "$MINIMUM_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then FOUND_AN_ENABLED_CHECK=1 if [ "$CAPACITY" -eq 0 ] ; then echo "WARNING: Battery does not report a capacity. Minimum battery" echo "charge checking does not work without a design capacity." ENOUGH_CHARGE=1 elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then FOUND_AN_ENABLED_HIBERNATION_CHECK=1 if [ "$CAPACITY" -eq 0 ] ; then echo "WARNING: Battery does not report a design capacity. Auto hibernation" echo "does not work without a design capacity." ENOUGH_CHARGE=1 elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi ALARM_LEVEL=$(cat $BATT/alarm) if [ "$ALARM_LEVEL" -ne 0 ] ; then if [ "$REMAINING" -le "$ALARM_LEVEL" ] ; then # Restore the state we had before checking this battery, so that # this battery does not count as having enough charge. ENOUGH_CHARGE=$PREV_ENOUGH_CHARGE elif [ "$FOUND_AN_ENABLED_CHECK" -eq 0 ] ; then # This is the only check that is enabled. In that case a non-critical # battery level counts as "enough". (If we would count non-critical # battery levels as enough *always*, then the other settings would # have no effect; this is only a final fallback.) ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then if [ "$REMAINING" -le "$ALARM_LEVEL" ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION elif [ "$FOUND_AN_ENABLED_HIBERNATION_CHECK" -eq 0 ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi # # Fallback: hard values # if [ "$IN_UAH" -ne 0 ] ; then if [ "$MINIMUM_BATTERY_CHARGE_MAH" -ne 0 ] ; then FOUND_AN_ENABLED_CHECK=1 if [ "$REMAINING" -ge $((1000*"$MINIMUM_BATTERY_CHARGE_MAH")) ] ; then ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" -ne 0 ] ; then FOUND_AN_ENABLED_HIBERNATION_CHECK=1 if [ "$REMAINING" -ge $((1000*"$AUTO_HIBERNATION_BATTERY_CHARGE_MAH")) ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi elif [ "$IN_UWH" -ne 0 ] ; then if [ "$MINIMUM_BATTERY_CHARGE_MWH" -ne 0 ] ; then FOUND_AN_ENABLED_CHECK=1 if [ "$REMAINING" -ge $((1000*"$MINIMUM_BATTERY_CHARGE_MWH")) ] ; then ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" -ne 0 ] ; then FOUND_AN_ENABLED_HIBERNATION_CHECK=1 if [ "$REMAINING" -ge $((1000*"$AUTO_HIBERNATION_BATTERY_CHARGE_MWH")) ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi else echo "Failed to determine battery charge. Battery charge units are not in" echo "mWh, uWh, mAh or uAh." fi else $LM_VERBOSE && echo "Battery is not present." >> $OUTPUT fi fi done elif [ "$(echo /proc/acpi/battery/*)" != '/proc/acpi/battery/*' ] ; then $LM_VERBOSE && echo "Not on AC and we have batteries in /proc/acpi/battery -- checking minimum battery charge." >> $OUTPUT for BATT in /proc/acpi/battery/* ; do PREV_ENOUGH_CHARGE=$ENOUGH_CHARGE PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION BATT_STATE=$BATT/state BATT_INFO=$BATT/info $LM_VERBOSE && echo "Checking info and state for $BATT." >> $OUTPUT # Only do if the battery is present if ( grep -q 'present:.*yes' $BATT_INFO ) ; then FOUND_AN_ENABLED_CHECK=0 FOUND_AN_ENABLED_HIBERNATION_CHECK=0 # Get the remaining capacity. REMAINING=`grep "remaining capacity:" $BATT_STATE | sed "s/.* \([0-9][0-9]* \).*/\1/" ` if [ -z "$REMAINING" ] ; then $LM_VERBOSE && echo "Battery does not report remaining charte. Perhaps it is not present?" >> $OUTPUT REMAINING=0 fi $LM_VERBOSE && echo "Remaining charge: $REMAINING" >> $OUTPUT CAPACITY=`grep "design capacity:" $BATT_INFO | sed "s/.* \([0-9][0-9]* \).*/\1/" ` if [ -z "$CAPACITY" ] ; then $LM_VERBOSE && echo "Battery does not report capacity. Perhaps it is not present?" >> $OUTPUT CAPACITY=0 fi $LM_VERBOSE && echo "Design capacity: $CAPACITY" >> $OUTPUT # Check the charge percentage if [ "$MINIMUM_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then FOUND_AN_ENABLED_CHECK=1 if [ "$CAPACITY" -eq 0 ] ; then echo "WARNING: Battery does not report a design capacity. Minimum battery" echo "charge checking does not work without a design capacity." ENOUGH_CHARGE=1 elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$MINIMUM_BATTERY_CHARGE_PERCENT" ] ; then ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" -ne 0 ] ; then FOUND_AN_ENABLED_HIBERNATION_CHECK=1 if [ "$CAPACITY" -eq 0 ] ; then echo "WARNING: Battery does not report a design capacity. Auto hibernation" echo "does not work without a design capacity." ENOUGH_CHARGE=1 elif [ "$(($REMAINING * 100 / $CAPACITY))" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_PERCENT" ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi # # Fallback: hard values. # # Determine the reporting unit. IN_MAH=0 IN_MWH=0 if ( grep -q mWh $BATT_INFO ) ; then IN_MWH=1 elif ( grep -q mAh $BATT_INFO ) ; then IN_MAH=1 fi if [ "$IN_MAH" -ne 0 ] ; then if [ "$MINIMUM_BATTERY_CHARGE_MAH" -ne 0 ] ; then FOUND_AN_ENABLED_CHECK=1 if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MAH" ] ; then ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" -ne 0 ] ; then FOUND_AN_ENABLED_HIBERNATION_CHECK=1 if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MAH" ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi elif [ "$IN_MWH" -ne 0 ] ; then if [ "$MINIMUM_BATTERY_CHARGE_MWH" -ne 0 ] ; then FOUND_AN_ENABLED_CHECK=1 if [ "$REMAINING" -ge "$MINIMUM_BATTERY_CHARGE_MWH" ] ; then ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" -ne 0 ] ; then FOUND_AN_ENABLED_HIBERNATION_CHECK=1 if [ "$REMAINING" -ge "$AUTO_HIBERNATION_BATTERY_CHARGE_MWH" ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi else echo "Failed to determine battery charge. Battery charge units are not in" echo "mWh or mAh." fi CAP_STATE=`sed -r 's/^capacity state:\s*(.*)\s*$/\1/;t;d' "$BATT_STATE"` if [ "$DISABLE_LAPTOP_MODE_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then if [ "$CAP_STATE" = "critical" ] ; then # Restore the state we had before checking this battery, so that # this battery does not count as having enough charge. ENOUGH_CHARGE=$PREV_ENOUGH_CHARGE elif [ "$FOUND_AN_ENABLED_CHECK" -eq 0 ] ; then # This is the only check that is enabled. In that case a non-critical # battery level counts as "enough". (If we would count non-critical # battery levels as enough *always*, then the other settings would # have no effect; this is only a final fallback.) ENOUGH_CHARGE=1 fi fi if [ "$AUTO_HIBERNATION_ON_CRITICAL_BATTERY_LEVEL" -ne 0 ] ; then if [ "$CAP_STATE" = "critical" ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=$PREV_ENOUGH_CHARGE_TO_PREVENT_HIBERNATION elif [ "$FOUND_AN_ENABLED_HIBERNATION_CHECK" -eq 0 ] ; then ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 fi fi else $LM_VERBOSE && echo "Battery is not present." >> $OUTPUT fi done else ENOUGH_CHARGE=1 ENOUGH_CHARGE_TO_PREVENT_HIBERNATION=1 $LM_VERBOSE && echo "Not on AC and could not check battery state -- data loss sensitive features stay enabled and auto-hibernation will not work." >> $OUTPUT fi if [ "$ENABLE_AUTO_HIBERNATION" -ne 0 -a "$ENOUGH_CHARGE_TO_PREVENT_HIBERNATION" -eq 0 ] ; then $LM_VERBOSE && echo "None of the batteries have a charge above the auto-hibernation level." >> $OUTPUT $LM_VERBOSE && echo "Starting hibernation." >> $OUTPUT $HIBERNATE_COMMAND # Don't continue -- if things are configured correctly, then we # will be called on resume. exit 0 fi if [ "$ENOUGH_CHARGE" -eq 0 ] ; then $LM_VERBOSE && echo "None of the batteries have a charge above the minimum level." >> $OUTPUT $LM_VERBOSE && echo "Deactivating data loss sensitive features." >> $OUTPUT ACTIVATE_WITH_POSSIBLE_DATA_LOSS=0 fi fi if [ "$INIT" -eq 0 ] ; then echo -n "Laptop mode " fi WAS_ACTIVE=0 if [ "$ACTIVATE" -eq 1 ] ; then echo -n "$STATE, active" if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 0 ] ; then echo -n " (Data-loss sensitive features disabled.)" fi echo else echo "$STATE, not active" fi # Finally, call laptop-mode-tools modules. The modules can use the settings # from the config files, but they may NOT assume the settings actually exist, # as no defaults have been given for them. # Note that the /usr/local/lib path is deprecated. export FORCE STATE ON_AC ACTIVATE ACTIVATE_WITH_POSSIBLE_DATA_LOSS KLEVEL KMINOR WAS_ACTIVE LM_VERBOSE for SCRIPT in /usr/share/laptop-mode-tools/modules/* /usr/local/lib/laptop-mode-tools/modules/* /usr/local/share/laptop-mode-tools/modules/* /etc/laptop-mode/modules/*; do if [ -x "$SCRIPT" ] ; then $LM_VERBOSE && echo "Invoking module $SCRIPT." >> $OUTPUT "$SCRIPT" >> $OUTPUT else $LM_VERBOSE && echo "Module $SCRIPT is not executable." >> $OUTPUT fi done exit 0 # This fi closes the if for "readconfig". If I would have indented this one # I would have indented the whole file. :) fi